/**
 * 当执行one的时候,会创建一个执行上下文
 * 编译阶段
 *   + 创建VO
 *     1. 处理参数,把参数放入VO(variable object)
 *     2. 扫描所有代码,找出function声明,从上往下一次执行
 *       在编译阶段,会处理所有的函数声明,如果有重复的声明,后面会覆盖前面的
 *     3. 扫描var关键字 var是不赋值的 只声明 值是undefined
 *     4. 在编译阶段是不会处理let、const的,let、const的变量也不会放在VO里,也不会作为windows上的属性
 *   + 确定子EC里申明函数的父级作用域
 *   + 确定this
 * 执行阶段
 *   从上往下逐行依次执行
 * */

//函数本身被创建的时候↓
//one[[SCOPE]] = [globalEC.VO]
function one(m, n) {
  //函数执行创建EC的时候↓
  //VO = {m,n}
  //VO = {m,n,fn:()=>1}
  //VO = {m,n,fn:()=>2}
  //VO = {m,n,fn:()=>2,b:undefined}
  //var fn会无视 什么都不做 因为var发现有同样名字的申明
  //oneEC = {VO,this:window,scopeChain:[oneVO,globalVO]}
  //创建阶段就是为执行阶段提供执行时的"材料"
  //代码从上往下逐行执行
  console.log(m, n);
  function fn() {
    console.log(1);
    return 1;
  }
  function fn(){
    console.log(2);
    return 2;
  }
  var b = 2;
  var fn = 3;
  let c = 4;
}

one(1, 2);



/** AO Activation Object*/
// 在函数的调用栈中，如果当前执行上下文处于函数调用栈的顶端，则意味着当前上下文处于激活状态，此时变量对象称为活动对象(AO,Activation Object) VO=>AO
// 活动变量包含变量对象所有的属性，并有包含this指针
// 有个直观的可观测AO的方法 即debugger时的 Scope->Local
 function one(m) {
    var a=1;
    debugger;
    console.log(this);//window
    function two() {;
        console.log(a,'two');
    }
    two();
}
one(1);
let globalVo = { one: 'fn one' };
let globalEC = { VO: globalVo, this: window, scopeChain: [globalVo] };
let ECStack = [];
ECStack.push(globalEC);
//===============================
let oneVo = { two: 'fn two' };
let oneEC = { VO: oneVo, this: window, scopeChain: [oneVo, globalVo] };
ECStack.push(oneEC);
//当one开始的时候，因为oneEC处于执行栈的顶端，这个时候，oneVo就会成为AO
//Activation Object oneVo.this = window
let twoVo = {};
let twoEC = { VO: twoVo, this: window, scopeChain: [twoVo, oneVo, globalVo] };
ECStack.push(twoEC);
//VO=>AO oneVo.this=window
ECStack.pop(twoEC);
ECStack.pop(oneEC);
